﻿using IPC.Communication;
using IPC.ListConnect.Connect;
using IPC.LogCommon.DelegateAndEvent;
using IPC.ListConnect.ListProprety;
using IPC.ListConnect.Profinet;
using IPC.WinForm.ControlExtend;
using IPC.LogCommon.log4net;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace IPC.WinForm.BaseForm
{
    public partial class FrmRealTimeValue : Form
    {
        private ChannelType _channelType = ChannelType.None;
        private EquipType _equipType = EquipType.None;
        private string _ip = string.Empty;
        private string _port = string.Empty;
        private string _slot = string.Empty;
        private string _rack = string.Empty;
        private string _connectName = string.Empty;
        private bool _isFirst = true;
        public static bool IsShow = false;
        private string selectedTreeNodeName = string.Empty;
        private string selectedTreeNodeText = string.Empty;
        private TreeNode selectedTreeNode;
        private CancellationTokenSource cts;
        private CancellationToken token;

        #region 单例
        private static FrmRealTimeValue _instance;
        public static FrmRealTimeValue Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new FrmRealTimeValue();
                }
                return _instance;
            }
        }
        #endregion

        #region 构造函数
        public FrmRealTimeValue()
        {
            InitializeComponent();
            DelegateAndEvent.Instance.AddAlarmInfoEvent += AddInfo;
            DelegateAndEvent.Instance.RefreshFrmWhenValueUpdateEvent += RefreshFrmWhenValueUpdate;
            this.treeView1.ExpandAll();
            LogClass.Instance.Info("初始化FrmRealTimeValue");
        }
        #endregion

        #region 展示
        public void ShowInstance()
        {
            if (IsShow)
            {
                _instance.WindowState = FormWindowState.Normal;
                return;
            }
            IsShow = true;
            foreach (EquipChannel equipChannel in EquipChannels.Instance.EquipChannelList)
            {
                foreach (Equip equip in equipChannel.Equips.Values)
                {
                    if (equip.Tags.Count > 0)
                    {
                        TreeNode treeNode = new TreeNode(equipChannel.ChannelName + "." + equip.Name);
                        treeNode.ImageKey = "folder-empty.png";
                        treeNode.Name = equip.EquipFullName;
                        treeNode.SelectedImageKey = "folder.png";
                        this.treeView1.Nodes[0].Nodes.Add(treeNode);
                    }

                    foreach (Group group in equip.Groups.Values)
                    {
                        if (group.Tags.Count > 0)
                        {
                            TreeNode treeNode = new TreeNode(equipChannel.ChannelName + "." + equip.Name + "." + group.Name);
                            treeNode.ImageKey = "folder-empty.png";
                            treeNode.Name = group.GroupFullName;
                            treeNode.SelectedImageKey = "folder.png";
                            this.treeView1.Nodes[0].Nodes.Add(treeNode);
                        }
                    }
                }
            }
            //_instance.TopMost = true;
            _instance.Show();
            _instance.WindowState = FormWindowState.Normal;
        }
        #endregion

        #region 析构

        ~FrmRealTimeValue()
        {
            IsShow = false;
            DelegateAndEvent.Instance.ClearFrmWhenValueUpdate();
            DelegateAndEvent.Instance.ClearAddAlarmInfo();
            DelegateAndEvent.Instance = null;
            cts.Cancel();
            LogClass.Instance.Info("释放FrmRealTimeValue");
        }
        #endregion

        #region 选中节点展示标签
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (cts != null)
            {
                cts.Cancel();
            }
            cts = new CancellationTokenSource();
            token = cts.Token;
            TreeNode treeNode = this.treeView1.SelectedNode;
            if (treeNode.Parent == null) //选中的是根节点
            {
                this.dataGridViewExtend1.Visible = false;
                selectedTreeNode = treeNode;
                selectedTreeNodeText = string.Empty;
                selectedTreeNodeName = string.Empty;
            }
            else
            {
                this.dataGridViewExtend1.Visible = true;
                string equipNames = treeNode.Text;
                LoadDataRow(equipNames);
                _isFirst = true;
                selectedTreeNode = treeNode;
                selectedTreeNodeText = selectedTreeNode.Text;
                selectedTreeNodeName = selectedTreeNode.Name;
                LogClass.Instance.Info($"刷新{selectedTreeNodeText}数据");
                RefreshData();
            }
        }
        #endregion

        #region 加载数据
        private void LoadDataRow(string equipName)
        {
            try
            {
                //this.dataGridViewExtend1.DataSource = null;
                DataTable dataTable = new DataTable();
                dataTable.Columns.Add("ItemID", typeof(string));
                dataTable.Columns.Add("DataType", typeof(string));
                dataTable.Columns.Add("Value", typeof(string));
                dataTable.Columns.Add("UpdateCount", typeof(string));
                dataTable.Columns.Add("FullName", typeof(string));
                dataTable.Columns.Add("Remark", typeof(string));
                string[] equipNames = equipName.Split('.');
                string channelName = equipNames[0];
                string equip = equipNames[1];
                string groupName = string.Empty;
                if (equipNames.Length > 2)
                {
                    groupName = equipNames[2];
                }
                foreach (var itemChannel in EquipChannels.Instance.EquipChannelList)
                {
                    if (itemChannel.ChannelName == channelName)
                    {
                        _connectName = itemChannel.ChannelName;
                        _channelType = (ChannelType)Enum.Parse(typeof(ChannelType), itemChannel.ChannelType);
                        foreach (var itemEquip in itemChannel.Equips.Values)
                        {
                            if (itemEquip.Name == equip)
                            {
                                _equipType = (EquipType)Enum.Parse(typeof(EquipType), itemEquip.Type);
                                _ip = itemEquip.Ip;
                                _port = itemEquip.Port;
                                _slot = itemEquip.Slot;
                                _rack = itemEquip.Rack;
                                if (String.IsNullOrWhiteSpace(groupName)) //是设备一级的标签
                                {
                                    foreach (var itemTag in itemEquip.Tags.Values)
                                    {
                                        DataRow dataRow = dataTable.NewRow();
                                        dataRow["ItemID"] = equipName + "." + itemTag.Name;
                                        dataRow["DataType"] = itemTag.DataType.ToString();
                                        dataRow["Value"] = itemTag.Value;
                                        dataRow["UpdateCount"] = itemTag.UpdateCount;
                                        dataRow["FullName"] = itemTag.FullName;
                                        dataRow["Remark"] = itemTag.Remark;
                                        dataTable.Rows.Add(dataRow);
                                    }
                                }
                                else
                                {
                                    foreach (var itemGroup in itemEquip.Groups.Values) //如果是组标签
                                    {
                                        if (itemGroup.Name == groupName)
                                        {
                                            foreach (var itemTag in itemGroup.Tags.Values)
                                            {
                                                DataRow dataRow = dataTable.NewRow();
                                                dataRow["ItemID"] = equipName + "." + itemTag.Name;
                                                dataRow["DataType"] = itemTag.DataType.ToString();
                                                dataRow["Value"] = itemTag.Value;
                                                dataRow["UpdateCount"] = itemTag.UpdateCount;
                                                dataRow["FullName"] = itemTag.FullName;
                                                dataRow["Remark"] = itemTag.Remark;
                                                dataTable.Rows.Add(dataRow);
                                            }
                                            break;
                                        }
                                    }
                                }
                                break;
                            }
                        }
                        break;
                    }
                }

                this.dataGridViewExtend1.DataSource = dataTable;
                this.dataGridViewExtend1.ClearSelection();
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"数据加载失败{equipName},{ex.Message}");
                this.richTextBox1.AppendText($"{DateTime.Now} 加载数据失败 {ex.Message} \n");
            }
        }
        #endregion

        #region 添加提示信息
        private delegate void AddInfoDelegate(string text);
        private void AddInfo(string text)
        {
            if (this.richTextBox1.InvokeRequired)
            {
                AddInfoDelegate addInfoDelegate = new AddInfoDelegate(AddInfo);
                this.richTextBox1.Invoke(addInfoDelegate, new object[] { text });
            }
            else
            {
                this.richTextBox1.AppendText($"{DateTime.Now} {text} \n");
                this.richTextBox1.SelectionStart = this.richTextBox1.Text.Length;
            }
        }
        #endregion

        #region 刷新数据
        public void RefreshFrmWhenValueUpdate(string value, string fullName, int updateCount)
        {
            foreach (DataGridViewRow item in this.dataGridViewExtend1.Rows)
            {
                if (item.Cells["FullName"].Value.ToString() == fullName)
                {
                    item.Cells["Value"].Value = value;
                    //int updateCount = int.Parse(item.Cells["UpdateCount"].Value.ToString());
                    item.Cells["UpdateCount"].Value = updateCount;
                }
            }
        }
        #endregion

        #region 定时器读取值
        private void RefreshData()
        {
        }
        #endregion

        #region 写
        /// <summary>
        /// 单点写
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 写ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridViewExtend1.SelectedRows.Count == 0)
                    return;

                DataGridViewRow dataGridViewRow = this.dataGridViewExtend1.SelectedRows[0];
                string tagFullName = dataGridViewRow.Cells["ItemID"].Value.ToString();
                string[] names = tagFullName.Split('.');
                string channelName = names[0];
                string equipName = names[1];
                string group = string.Empty;
                string tagName = string.Empty;
                if (names.Length > 3)
                {
                    group = names[2];
                    tagName = names[3];
                }
                else
                {
                    tagName = names[2];
                }
                BaseConnect baseConnect = null;
                OperateResult operateResult = null;
                FrmWriteTag frmWriteTag = new FrmWriteTag(tagFullName);
                if (frmWriteTag.ShowDialog() == DialogResult.OK)
                {
                    if (_channelType != ChannelType.None)
                    {
                        string value = frmWriteTag.Value;
                        switch (_channelType)
                        {
                            case ChannelType.Virtual:
                                operateResult = ConnectList.Instance.Write(channelName, equipName, tagName, value, group);
                                break;
                            default:
                                operateResult = ConnectList.Instance.Write(channelName, equipName, tagName, value, group);
                                break;
                        }

                        if (operateResult.IsSuccess)
                        {
                            DelegateAndEvent.Instance.AddAlarmInfo($"写入{tagFullName}成功");
                            LogClass.Instance.Info($"写入数据成功{tagFullName},值{value}");
                        }
                        else
                        {
                            DelegateAndEvent.Instance.AddAlarmInfo($"写入{tagFullName}失败。{operateResult.Message}");
                            LogClass.Instance.Warn($"写入{tagFullName}失败。{operateResult.Message}");
                        }
                    }
                    else
                    {
                        DelegateAndEvent.Instance.AddAlarmInfo($"写入{tagFullName}错误，设备类型不支持");
                        LogClass.Instance.Warn($"写入{tagFullName}错误。设备类型不支持");
                    }
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"写入错误{ex.Message}");
                DelegateAndEvent.Instance.AddAlarmInfo($"写入错误 {ex.Message}");
            }
        }
        #endregion

        #region 窗口关闭
        private void FrmRealTimeValue_FormClosing(object sender, FormClosingEventArgs e)
        {
            IsShow = false;
            e.Cancel = true;
            _instance.Hide();
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add("ItemID", typeof(string));
            dataTable.Columns.Add("DataType", typeof(string));
            dataTable.Columns.Add("Value", typeof(string));
            dataTable.Columns.Add("UpdateCount", typeof(string));
            dataTable.Columns.Add("FullName", typeof(string));
            dataTable.Columns.Add("Remark", typeof(string));
            this.dataGridViewExtend1.DataSource = dataTable;
            this.treeView1.Nodes[0].Nodes.Clear();
            if (cts != null)
            {
                cts.Cancel();
            }
        }
        #endregion

        #region 右键选中行
        private void dataGridViewExtend1_MouseDown(object sender, MouseEventArgs e)
        {
            int index = GetRowIndexAt(e.Location.Y);
            if (index >= 0)
            {
                this.dataGridViewExtend1.Rows[index].Selected = true;
            }
        }
        #endregion

        #region 获取行号
        public int GetRowIndexAt(int mouseLocation_Y)
        {
            if (dataGridViewExtend1.FirstDisplayedScrollingRowIndex < 0)
            {
                return -1;  // no rows.   
            }
            if (dataGridViewExtend1.ColumnHeadersVisible == true && mouseLocation_Y <= dataGridViewExtend1.ColumnHeadersHeight)
            {
                return -1;
            }
            int index = dataGridViewExtend1.FirstDisplayedScrollingRowIndex;
            int displayedCount = dataGridViewExtend1.DisplayedRowCount(true);
            for (int k = 1; k <= displayedCount;)  // 因为行不能ReOrder，故只需要搜索显示的行   
            {
                if (dataGridViewExtend1.Rows[index].Visible == true)
                {
                    Rectangle rect = dataGridViewExtend1.GetRowDisplayRectangle(index, true);  // 取该区域的显示部分区域   
                    if (rect.Top <= mouseLocation_Y && mouseLocation_Y < rect.Bottom)
                    {
                        return index;
                    }
                    k++;  // 只计数显示的行;   
                }
                index++;
            }
            return -1;
        }
        #endregion

        #region 异步写
        private async void 异步写ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.dataGridViewExtend1.SelectedRows.Count == 0)
                    return;

                DataGridViewRow dataGridViewRow = this.dataGridViewExtend1.SelectedRows[0];
                string tagFullName = dataGridViewRow.Cells["ItemID"].Value.ToString();
                string[] names = tagFullName.Split('.');
                string channelName = names[0];
                string equipName = names[1];
                string group = string.Empty;
                string tagName = string.Empty;
                if (names.Length > 3)
                {
                    group = names[2];
                    tagName = names[3];
                }
                else
                {
                    tagName = names[2];
                }
                BaseConnect baseConnect = null;
                OperateResult operateResult = null;
                FrmWriteTag frmWriteTag = new FrmWriteTag(tagFullName);
                if (frmWriteTag.ShowDialog() == DialogResult.OK)
                {
                    Task task = new Task(() =>
                    {
                        if (_channelType != ChannelType.None)
                        {
                            string value = frmWriteTag.Value;
                            switch (_channelType)
                            {
                                case ChannelType.Virtual:
                                    baseConnect = new VirtualConnect(_connectName, _ip, 0, 0, 0);
                                    operateResult = baseConnect.Write(channelName, equipName, tagName, value, group);
                                    break;
                                default:
                                    operateResult = ConnectList.Instance.Write(channelName, equipName, tagName, value, group);
                                    break;
                            }

                            if (operateResult.IsSuccess)
                            {
                                DelegateAndEvent.Instance.AddAlarmInfo($"写入{tagFullName}成功");
                                LogClass.Instance.Info($"异步写入数据成功{tagFullName},值{value}");
                            }
                            else
                            {
                                DelegateAndEvent.Instance.AddAlarmInfo($"写入{tagFullName}失败。{operateResult.Message}");
                                LogClass.Instance.Warn($"异步写入{tagFullName}失败。{operateResult.Message}");
                            }
                        }
                        else
                        {
                            DelegateAndEvent.Instance.AddAlarmInfo($"写入{tagFullName}错误，设备类型不支持");
                            LogClass.Instance.Warn($"异步写入{tagFullName}错误。设备类型不支持");
                        }
                    });
                    task.Start();
                    await task;
                    task.Dispose();
                }
            }
            catch (Exception ex)
            {
                LogClass.Instance.Error($"写入错误{ex.Message}");
                DelegateAndEvent.Instance.AddAlarmInfo($"写入错误 {ex.Message}");
            }
        } 
        #endregion
    }
}
